一、概念
选择器(selector)是selectableChannel对象的多路复用器,一个selector可以监控多个selectableChannel的io情况,selector可以实现一个线程单独管理多个channel,selector是非阻塞的核心
二、selector可以监控的事件类型
- connect 客户端连接服务端事件
 
- accept 服务端接受服务端事件
 
- read   读事件
 
- write  写事件  
 
每次请求都是从客户端连接服务端(connect),服务端开始准备(accept),准备完成后开始读数据,处理完成之后再写数据
三、selector的常用方法

四、nio 的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
   | //服务端 public class NioServer {     private ServerSocketChannel serverSocketChannel;     private Selector selector;     private Integer port = 8080;
      NioServer() {         try {             serverSocketChannel = ServerSocketChannel.open().bind(new InetSocketAddress(port));             //设置非阻塞             serverSocketChannel.configureBlocking(false);             //创建Selector             selector = Selector.open();             //注册tcp 连接事件到 channel             serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);             System.out.println("服务端初始化完成,端口号:" + port);         } catch (Exception ex) {             throw new RuntimeException("初始化服务端失败,ex:"+ex);         }     }
      private void start() {         try {             //获取查看selector 管理多少个channel             while (selector.select() > 0) {                 //走到这里肯定是selector发现channel有变化了,这个大哥把他管理的sekectedKeys拿出来遍历                 Set<SelectionKey> selectionKeys = selector.selectedKeys();                 Iterator<SelectionKey> iterator = selectionKeys.iterator();                 while (iterator.hasNext()) {                     SelectionKey selectionKey = iterator.next();                     //selector 也不知道是什么变化所以就 各种判断一下,是 创建连接、还是准备就绪、还是读取数据、还是写数据、还是关闭连接                     if (selectionKey.isConnectable()) {                         System.out.println("用户建立连接");                     }                     if (selectionKey.isAcceptable()) {                         System.out.println("用户准备就绪");                         ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();                         //这样就拿到了发生变化的 socketChannel
                          SocketChannel accept = serverSocketChannel.accept();                         accept.configureBlocking(false);                         //把客户端的channel 注册到 selector 当客户端的socketChannel发生变化出发读逻辑                         accept.register(selector, SelectionKey.OP_READ);                     }                     if (selectionKey.isReadable()) {                         System.out.println("读数据");                         SocketChannel socketChannel = (SocketChannel) selectionKey.channel();                         //读数据得是由buffer                         ByteBuffer byteBuffer = ByteBuffer.allocate(1024);                         //切换到读模式                         StringBuffer sb = new StringBuffer();                         while (socketChannel.read(byteBuffer) != -1) {                             byteBuffer.flip();                             sb.append(StandardCharsets.UTF_8.decode(byteBuffer));                             byteBuffer.clear();                         }                         System.out.println("来自客户端的问候:" + sb.toString());                         //来个写数据吧                         socketChannel.register(selector,SelectionKey.OP_WRITE);                     }                     if (selectionKey.isWritable()) {                         System.out.println("写数据");                         System.out.println("不会写数据");                         selectionKey.channel().close();                     }                     if (selectionKey.isValid()) {                         System.out.println("关闭数据");                     }                     //把当前的selection移除,因为后面事件还会加入                     iterator.remove();                 }             }         } catch (Exception ex) {             throw new RuntimeException("服务异,ex:", ex);         }
 
      }
      public static void main(String[] args) {         //先定义服务端         NioServer nioServer = new NioServer();         //开启服务         nioServer.start();     }
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | //客户端 public class NioClint {
      public static void main(String[] args) throws IOException {         SocketChannel open = SocketChannel.open();         open.connect(new InetSocketAddress("127.0.0.1",8080));         open.configureBlocking(false);         ByteBuffer byteBuffer =ByteBuffer.allocate(1024);         byteBuffer.flip();         String msg ="呵呵,你大爷";         byteBuffer = ByteBuffer.wrap(msg.getBytes("utf-8"));         open.write(byteBuffer);         byteBuffer.clear();         Socket socket = open.socket();         SocketChannel channel = socket.getChannel();     } }
 
   |